package com.yike.user.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yike.common.base.BaseServiceImpl;
import com.yike.common.exception.BusinessException;
import com.yike.common.pagination.PageInfo;
import com.yike.common.pagination.Paging;
import com.yike.common.tool.LoginUtil;
import com.yike.common.tool.StringUtil;
import com.yike.user.dto.MachineDTO;
import com.yike.user.dto.SalesReportDataDTO;
import com.yike.user.entity.Agent;
import com.yike.user.entity.Machine;
import com.yike.user.entity.Shop;
import com.yike.user.mapper.AgentMapper;
import com.yike.user.mapper.MachineMapper;
import com.yike.user.mapper.ShopMapper;
import com.yike.user.param.BaseMachineParam;
import com.yike.user.param.MachineParam;
import com.yike.user.param.PlatformMachineInfoParam;
import com.yike.user.param.PlatformMachinePageParam;
import com.yike.user.service.PlatformMachineService;
import com.yike.user.vo.PlatformBaseMachineVo;
import com.yike.user.vo.PlatformMachineInfoVo;
import com.yike.user.vo.PlatformMachineVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 平台设备 服务实现类
 *
 * @author Sakura
 * @since 2024-11-07
 */
@Slf4j
@Service
public class PlatformMachineServiceImpl extends BaseServiceImpl<MachineMapper, Machine> implements PlatformMachineService {

    @Autowired
    private MachineMapper machineMapper;
    @Autowired
    private AgentMapper agentMapper;
    @Autowired
    private ShopMapper shopMapper;

    @Override
    @Transactional
    public boolean addMachine(MachineParam machineParam) throws Exception {
        for (BaseMachineParam baseMachineParam:machineParam.getMachines()) {
            // 校验设备号是否重复
            Machine machine = machineMapper.selectOne(Wrappers.lambdaQuery(Machine.class)
                    .eq(Machine::getMacNo, baseMachineParam.getMacNo()));
            if (machine != null) {
                throw new BusinessException("当前设备号已存在");
            }
            machine = new Machine();
            BeanUtils.copyProperties(baseMachineParam, machine);
            machine.setShopId(machineParam.getShopId());
            machine.setAgentId(machineParam.getAgentId());
            machine.setCreateBy(LoginUtil.getUserId());
            machine.setBindTime(new Date());
            machineMapper.insert(machine);
        }
        return true;
    }

    @Override
    public boolean updateMachine(MachineParam machineParam) throws Exception {
        for (BaseMachineParam baseMachineParam:machineParam.getMachines()) {
            Machine machine = machineMapper.selectOne(Wrappers.lambdaQuery(Machine.class)
                    .eq(Machine::getMacNo, baseMachineParam.getMacNo()));
            if (machine != null) {
                // 判断是否绑定了其它代理商
                if (machine.getAgentId() != null && !machine.getAgentId().equals(machineParam.getAgentId())) {
                    throw new BusinessException("当前设备已绑定其他代理商");
                }
                // 判断是否已绑定店铺
                if (machine.getShopId() != null && machineParam.getShopId() != null && !machine.getShopId().equals(machineParam.getShopId())) {
                    throw new BusinessException("当前设备已绑定其它店铺");
                }
                if (machine.getShopId() == null && machineParam.getShopId() != null) {
                    machine.setBindTime(new Date());
                }
                BeanUtils.copyProperties(baseMachineParam, machine);
                machine.setShopId(machineParam.getShopId());
                machine.setAgentId(machineParam.getAgentId());
                machine.setCreateBy(LoginUtil.getUserId());
                machineMapper.updateById(machine);
            } else {
                machine = new Machine();
                BeanUtils.copyProperties(baseMachineParam, machine);
                machine.setShopId(machineParam.getShopId());
                machine.setAgentId(machineParam.getAgentId());
                machine.setCreateBy(LoginUtil.getUserId());
                machine.setBindTime(new Date());
                machineMapper.insert(machine);
            }
        }

        return true;
    }

    @Override
    public void exportTemplate(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 设置导出参数，表头显示为"设备列表"
        ExportParams exportParams = new ExportParams(null, "设备列表");

        // 生成工作簿，使用空数据列表导出只有表头的 Excel
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, MachineDTO.class, new ArrayList<>());

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");

        // 设置文件名，并对中文进行 URL 编码
        String fileName = URLEncoder.encode("设备列表.xlsx", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);

        // 写入到响应流
        workbook.write(response.getOutputStream());
        workbook.close();
    }

    @Override
    public boolean importMachine(MultipartFile file) throws Exception {
        // 设置导入参数
        ImportParams params = new ImportParams();
        //params.setTitleRows(1);  // 表头占的行数
        params.setHeadRows(1);   // 列名占的行数

        // 读取 Excel 文件并解析为对象列表
        List<MachineDTO> machineDTOS = ExcelImportUtil.importExcel(
                file.getInputStream(),
                MachineDTO.class,
                params
        );
        if (machineDTOS == null || machineDTOS.size() == 0) {
            throw new BusinessException("导入数据为空");
        }
        //先验证数据是否正常再批量保存
        List<Machine> machines = new ArrayList<>(machineDTOS.size());
        List<String> errorList = new ArrayList<>(machineDTOS.size());
        int i = 1;
        for (MachineDTO machineDTO : machineDTOS) {
            if (StringUtil.isBlank(machineDTO.getMacNo())) {
                i++;
                errorList.add("第 " + i + " 行设备编号为空");
                continue;
            }
            // 校验设备号是否重复
            Machine machine = machineMapper.selectOne(Wrappers.lambdaQuery(Machine.class)
                    .eq(Machine::getMacNo, machineDTO.getMacNo()));
            if (machine != null) {
                errorList.add("设备编号：" + machineDTO.getMacNo() + " 已存在");
            }
            machine = new Machine();
            BeanUtils.copyProperties(machineDTO, machine);

            // 如果代理商编号不为空需要判断代理商信息是否正常
            if (StringUtil.isNotBlank(machineDTO.getAgentNo())) {
                Agent agent = agentMapper.selectOne(Wrappers.lambdaQuery(Agent.class)
                        .eq(Agent::getAgentNo, machineDTO.getAgentNo()));
                if (agent == null) {
                    errorList.add("代理商编号：" + machineDTO.getAgentNo() + " 不存在");
                } else {
                    machine.setAgentId(agent.getId());
                }
            }
            // 如果店铺编号不为空则需要判断店铺信息是否正常
            if (StringUtil.isNotBlank(machineDTO.getShopNo())) {
                Shop shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                        .eq(Shop::getShopNo, machineDTO.getShopNo()));
                if (shop == null) {
                    errorList.add("店铺编号：" + machineDTO.getShopNo() + " 不存在");
                } else {
                    machine.setShopId(shop.getId());
                }
            }

            machine.setCreateBy(LoginUtil.getUserId());
            machines.add(machine);
        }
        if (errorList.size() > 0) {
            throw new BusinessException(errorList.toString());
        }
        // 批量保存
        super.saveBatch(machines);
        return true;
    }

    @Override
    public Paging<PlatformMachineVo> getPlatformMachineList(PlatformMachinePageParam platformMachinePageParam) throws Exception {
        Page<Machine> page = new PageInfo<>(platformMachinePageParam);
        IPage<PlatformMachineVo> iPage = machineMapper.getPlatformMachineList(page, platformMachinePageParam);
        return new Paging<PlatformMachineVo>(iPage);
    }

    @Override
    public PlatformMachineInfoVo getInfo(PlatformMachineInfoParam platformMachineInfoParam) throws Exception {
        List<PlatformMachineVo> machines = machineMapper.getMachineList(platformMachineInfoParam);
        return convertToMachineInfoVo(machines);
    }

    @Override
    public PlatformMachineVo getPlatformMachine(Long id) throws Exception {
        return machineMapper.getPlatformMachineVo(id);
    }

    @Override
    public boolean unbind(Long id) throws Exception {
        // 获取设备信息
        Machine machine = machineMapper.selectById(id);
        if (machine == null) {
            throw new BusinessException("设备信息异常");
        }
        // 去掉店铺绑定ID
        machineMapper.update(machine, new LambdaUpdateWrapper<Machine>()
                .set(Machine::getShopId, null)
                .set(Machine::getBindTime, null)
                .eq(Machine::getId, id));

        return true;
    }

    @Override
    public boolean delete(Long id) throws Exception {
        // 获取设备信息
        Machine machine = machineMapper.selectById(id);
        if (machine == null) {
            throw new BusinessException("设备信息异常");
        }
        machineMapper.deleteById(id);

        return true;
    }

    public PlatformMachineInfoVo convertToMachineInfoVo(List<PlatformMachineVo> machineVoList) {
        if (machineVoList == null || machineVoList.isEmpty()) {
            return null;
        }

        // 取第一个元素作为基础信息
        PlatformMachineVo firstMachine = machineVoList.get(0);
        PlatformMachineInfoVo infoVo = new PlatformMachineInfoVo();

        infoVo.setShopId(firstMachine.getShopId());
        infoVo.setShopName(firstMachine.getShopName());
        infoVo.setProvCode(firstMachine.getProvCode());
        infoVo.setProvName(firstMachine.getProvName());
        infoVo.setCityCode(firstMachine.getCityCode());
        infoVo.setCityName(firstMachine.getCityName());
        infoVo.setDistCode(firstMachine.getDistCode());
        infoVo.setDistName(firstMachine.getDistName());
        infoVo.setAddress(firstMachine.getAddress());
        infoVo.setContact(firstMachine.getContact());
        infoVo.setMobile(firstMachine.getMobile());
        infoVo.setAgentId(firstMachine.getAgentId());
        infoVo.setAgentNo(firstMachine.getAgentNo());
        infoVo.setAgentName(firstMachine.getAgentName());

        // 转换设备信息
        List<PlatformBaseMachineVo> baseMachines = machineVoList.stream().map(machine -> {
            PlatformBaseMachineVo baseVo = new PlatformBaseMachineVo();
            baseVo.setId(machine.getId());
            baseVo.setName(machine.getName());
            baseVo.setMacNo(machine.getMacNo());
            baseVo.setMacSn(machine.getMacSn());
            baseVo.setModel(machine.getModel());
            baseVo.setType(machine.getType());
            baseVo.setRemark(machine.getRemark());
            baseVo.setBindTime(machine.getBindTime());
            baseVo.setStatus(machine.getStatus());
            baseVo.setLineStatus(machine.getLineStatus());
            return baseVo;
        }).collect(Collectors.toList());

        infoVo.setMachines(baseMachines);
        return infoVo;
    }

}
